import re
import matplotlib.pyplot as plt
from math import *
import numpy as np


def dp_fuzhi(dp):
    # 设置初始化角度，并且转化为弧度
    theta = 30 * pi / 180
    # 定义种子点
    dp[0][0] = 1
    dp[1][0] = sqrt(3) * cos(theta)
    dp[1][1] = sqrt(3) * sin(theta)

    # 求出坐标为[i,i],[i,i-1]的点
    for i in range(2, l):
        f1 = sqrt((2 * i + 1) / (2 * i))
        f2 = sqrt(2 * i + 1)
        dp[i][i] = f1 * sin(theta) * dp[i - 1][i - 1]
        dp[i][i - 1] = f2 * cos(theta) * dp[i - 1][i - 1]

    # 使用前面的结果递推出坐标为[row,lie]的点
    for lie in range(0, l):
        for row in range(lie + 2, l):
            f3 = sqrt((2 * row + 1) / ((row - lie) * (row + lie)))
            f4 = sqrt(2 * row - 1)
            f5 = sqrt(((row - lie - 1) * (row + lie - 1)) / (2 * row - 3))
            dp[row][lie] = (
                f3 * f4 * cos(theta) * dp[row - 1][lie] - f3 * f5 * dp[row - 2][lie]
            )

    # 将矩阵多余值设为空
    for i in range(0, l):
        for j in range(i, l - 1):
            dp[i][j + 1] = None


def dp_output(dp, filename):
    # 创建结果展示列表show_p
    show_p = list()

    # 标题设置"{:<7s}{:<6s}{:.16s}\n"为占位符，分别表示"L","M","P_l_m"
    show_p.append("{:<7s}{:<6s}{:.16s}\n".format("L", "M", "P_l_m"))

    # 对show_p列表进行填充
    for i in range(0, l):
        for j in range(0, i + 1):
            line = "{:<7d}{:<6d}{:.16f}\n".format(int(i), int(j), dp[i][j])
            show_p.append(line)
        show_p.append("\n")

    # print文件数据
    print("".join(show_p))

    # 输出结果到文件刘维康.txt
    with open(filename, "w") as f:
        f.writelines(show_p)


def l_paint(outfilename):
    l = int(input("请输入你想绘制的行数: l="))

    date = []

    with open(outfilename, "r", encoding="utf-8") as f:
        for line in f:
            try:
                get_l = int(line[:3])
            except:
                get_l = -1

            if get_l == l:
                date.append(line.strip())

    show_x = []
    show_y = []

    for i in range(0, len(date)):
        d_line = re.split(r"\s+", date[i])
        show_x.append(float(d_line[1]))
        show_y.append(float(d_line[2]))

    plt.title(f"l={l}")
    plt.xlabel("m")
    plt.ylabel("P[l][m]")
    plt.xticks(show_x, rotation=-90)
    plt.scatter(show_x, show_y)
    plt.savefig(f"P[{l}][ ].png")
    plt.show()


def main():
    output_name = "刘维康.txt"
    # 定义初始值
    global l
    l = 181
    # 初始化dp，创建181x181的矩阵
    dp = np.zeros((l, l))
    # 调用函数赋值
    dp_fuzhi(dp)
    # 调用函数输出结果
    dp_output(dp, output_name)
    # 画图
    l_paint(output_name)


if __name__ == "__main__":
    main()
